home *** CD-ROM | disk | FTP | other *** search
/ The World's Largest Collection of Windows Software / The World's Largest Collection of Windows Software - Disc 2.iso / textproc / _j1 / tex2rtf / src / tex2any.cc < prev    next >
C/C++ Source or Header  |  1993-10-26  |  54KB  |  1,991 lines

  1. /*
  2.  * File:     tex2any.cc
  3.  * Purpose:  Conversion utility for LaTeX files
  4.  *
  5.  *                       wxWindows 1.50
  6.  * Copyright (c) 1993 Artificial Intelligence Applications Institute,
  7.  *                   The University of Edinburgh
  8.  *
  9.  *                     Author: Julian Smart
  10.  *                        Date: 7-9-93
  11.  *
  12.  * Permission to use, copy, modify, and distribute this software and its
  13.  * documentation for any purpose is hereby granted without fee, provided
  14.  * that the above copyright notice, author statement and this permission
  15.  * notice appear in all copies of this software and related documentation.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
  18.  * IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
  19.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  20.  *
  21.  * IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
  22.  * UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
  23.  * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
  24.  * LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
  25.  * DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
  26.  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <wx.h>
  30. #include <ctype.h>
  31. #include "tex2any.h"
  32. #include <stdlib.h>
  33. #include <time.h>
  34.  
  35. /*
  36.  * Variables accessible from clients
  37.  *
  38.  */
  39.  
  40. TexChunk *      DocumentTitle = NULL;
  41. TexChunk *      DocumentAuthor = NULL;
  42. TexChunk *      DocumentDate = NULL;
  43. char *          CurrentLabel = NULL;
  44. int             DocumentStyle = LATEX_REPORT;
  45. int             MinorDocumentStyle = 0;
  46. wxPathList      TexPathList;
  47. char *          BibliographyStyleString = copystring("plain");
  48. char *          DocumentStyleString = copystring("report");
  49. int             ParSkip = 0;
  50. int             ParIndent = 0;
  51.  
  52. int             normalFont = 10;
  53. int             smallFont = 8;
  54. int             tinyFont = 6;
  55. int             largeFont1 = 12;
  56. int             LargeFont2 = 14;
  57. int             LARGEFont3 = 18;
  58. int             hugeFont1 = 20;
  59. int             HugeFont2 = 24;
  60. int             HUGEFont3 = 28;
  61.  
  62. // Section font sizes
  63. int             chapterFont =    LARGEFont3;
  64. int             sectionFont =    LargeFont2;
  65. int             subsectionFont = largeFont1;
  66.  
  67. /*
  68.  * Section numbering
  69.  *
  70.  */
  71.  
  72. int             chapterNo = 0;
  73. int             sectionNo = 0;
  74. int             subsectionNo = 0;
  75. int             subsubsectionNo = 0;
  76. int             figureNo = 0;
  77.  
  78. /*
  79.  * Other variables
  80.  *
  81.  */
  82.  
  83. FILE *CurrentOutput1 = NULL;
  84. FILE *CurrentOutput2 = NULL;
  85. FILE *Inputs[15];
  86. int CurrentInputIndex = 0;
  87. char TexFileRoot[300];
  88. char TexBibName[300];         // Bibliography output file name
  89. char TexTmpBibName[300];      // Temporary bibliography output file name
  90.  
  91. static int currentColumn = 0;
  92. char currentArgData[2000];
  93. Bool haveArgData = FALSE; // If TRUE, we're simulating the data.
  94. TexChunk *currentArgument = NULL;
  95. TexChunk *nextChunk = NULL;
  96. Bool isArgOptional = FALSE;
  97. Bool noArgs = 0;
  98.  
  99. TexChunk *TopLevel = NULL;
  100. wxList MacroDefs(wxKEY_STRING);
  101. wxStringList IgnorableInputFiles; // Ignorable \input files, e.g. psbox.tex
  102. char *BigBuffer = NULL;  // For reading in large chunks of text
  103. TexMacroDef *SoloBlockDef = NULL;
  104.  
  105. void TexOutput(char *s, Bool ordinaryText)
  106. {
  107.   int len = strlen(s);
  108.  
  109.   // Update current column, but only if we're guaranteed to
  110.   // be ordinary text (not mark-up stuff)
  111.   if (ordinaryText)
  112.     for (int i = 0; i < len; i++)
  113.     {
  114.       if (s[i] == 13 || s[i] == 10)
  115.         currentColumn = 0;
  116.       else
  117.         currentColumn ++;
  118.     }
  119.  
  120.   if (CurrentOutput1)
  121.     fprintf(CurrentOutput1, "%s", s);
  122.   if (CurrentOutput2)
  123.     fprintf(CurrentOutput2, "%s", s);
  124. }
  125.  
  126. /*
  127.  * Try to find a Latex macro, in one of the following forms:
  128.  * (1) \begin{} ... \end{}
  129.  * (2) \macroname{arg1}...{argn}
  130.  * (3) {\bf arg1}
  131.  */
  132.  
  133. TexMacroDef *MatchMacro(char *buffer, int *pos, char **env, Bool *parseToBrace)
  134. {
  135.   *parseToBrace = TRUE;
  136.   int i = (*pos);
  137.   TexMacroDef *def = NULL;
  138.  
  139.   // First, try to find begin{thing}
  140.   if (strncmp(buffer+i, "begin{", 6) == 0)
  141.   {
  142.     i += 6;
  143.  
  144.     wxNode *node = MacroDefs.First();
  145.     while (node && !def)
  146.     {
  147.       if (strncmp(buffer+i, node->key.string, strlen(node->key.string)) == 0)
  148.       { def = (TexMacroDef *)node->Data();
  149.         i += strlen(node->key.string); }
  150.       else node = node->Next();
  151.     }
  152.     if (def)
  153.     {
  154.       *pos = i + 1;
  155.       *env = def->name;
  156.       return def;
  157.     }
  158.     else return NULL;
  159.   }
  160.  
  161.   // Failed, so try to find macro from definition list
  162.   wxNode *node = MacroDefs.First();
  163.   while (node && !def)
  164.   {
  165.     if (strncmp(buffer+i, node->key.string, strlen(node->key.string)) == 0)
  166.     { def = (TexMacroDef *)node->Data();
  167.       i += strlen(node->key.string); }
  168.     else node = node->Next();
  169.   }
  170.   if (def)
  171.   {
  172.     // We want to check whether this is a space-consuming macro
  173.     // (e.g. {\bf word})
  174.     // No brace, e.g. \input thing.tex instead of \input{thing}
  175.     if ((def->no_args > 0) && ((buffer[i] == 32) || (buffer[i] == '=')))
  176.     {
  177.       i ++;
  178.       *parseToBrace = FALSE;
  179.     }
  180.     *pos = i;
  181.     return def;
  182.   }
  183.   return NULL;
  184. }
  185.  
  186. Bool FindEndEnvironment(char *buffer, int *pos, char *env)
  187. {
  188.   int i = (*pos);
  189.  
  190.   // Try to find end{thing}
  191.   if ((strncmp(buffer+i, "end{", 4) == 0) &&
  192.       (strncmp(buffer+i+4, env, strlen(env)) == 0))
  193.   {
  194.     *pos = i + 5 + strlen(env);
  195.     return TRUE;
  196.   }
  197.   else return FALSE;
  198. }
  199.  
  200. Bool readingVerbatim = FALSE;
  201. Bool readInVerbatim = FALSE;  // Within a verbatim, but not nec. verbatiminput
  202.  
  203. Bool read_a_line(char *buf)
  204. {
  205.   if (CurrentInputIndex < 0)
  206.   {
  207.     buf[0] = 0;
  208.     return FALSE;
  209.   }
  210.   
  211.   int ch = -2;
  212.   int i = 0;
  213.   buf[0] = 0;
  214.   while (ch != EOF && ch != 10)
  215.   {
  216.     ch = getc(Inputs[CurrentInputIndex]);
  217.     if (ch != EOF)
  218.     {
  219.       // Check for 2 consecutive newlines and replace with \par
  220.       if (ch == 10 && !readInVerbatim)
  221.       {
  222.         int ch1 = getc(Inputs[CurrentInputIndex]);
  223.         if ((ch1 == 10) || (ch1 == 13))
  224.         {
  225.           // Eliminate newline (10) following DOS linefeed
  226.           if (ch1 == 13) ch1 = getc(Inputs[CurrentInputIndex]);
  227.           buf[i] = 0;
  228.           strcat(buf, "\\par\n");
  229.           i += 6;
  230.         }
  231.         else
  232.         {
  233.           ungetc(ch1, Inputs[CurrentInputIndex]);
  234.           buf[i] = ch;
  235.           i ++;
  236.         }
  237.       }
  238.       else
  239.       {
  240.         buf[i] = ch;
  241.         i ++;
  242.       }
  243.     }
  244.     else
  245.     {
  246.       buf[i] = 0;
  247.       fclose(Inputs[CurrentInputIndex]);
  248.       Inputs[CurrentInputIndex] = NULL;
  249.       if (CurrentInputIndex > 0) ch = ' '; // No real end of file
  250.       CurrentInputIndex --;
  251.       if (readingVerbatim)
  252.       {
  253.         readingVerbatim = FALSE;
  254.         readInVerbatim = FALSE;
  255.         strcat(buf, "\\end{verbatim}\n");
  256.         return FALSE;
  257.       }
  258.     }
  259.   }
  260.   buf[i] = 0;
  261.  
  262.   // Read a verbatim input file as if it were a verbatim environment
  263.   if (strncmp(buf, "\\verbatiminput", 14) == 0)
  264.   {
  265.     int wordLen = 14;
  266.     char *fileName = buf + wordLen + 1;
  267.  
  268.     int j = i - 1;
  269.     buf[j] = 0;
  270.  
  271.     // thing}\par -- eliminate the \par!
  272.     if (strncmp((buf + strlen(buf)-5), "\\par", 4) == 0)
  273.     {
  274.       j -= 5;
  275.       buf[j] = 0;
  276.     }
  277.     
  278.     if (buf[j-1] == '}') buf[j-1] = 0; // Ignore final brace
  279.  
  280.     char *actualFile = TexPathList.FindValidPath(fileName);
  281.     if (!actualFile)
  282.     {
  283.       char errBuf[300];
  284.       strcpy(errBuf, "Could not find file: ");
  285.       strncat(errBuf, fileName, 100);
  286.       OnError(errBuf);
  287.     }
  288.     else
  289.     {
  290.       CurrentInputIndex ++;
  291.       Inputs[CurrentInputIndex] = fopen(actualFile, "r");
  292.       if (!Inputs[CurrentInputIndex])
  293.       {
  294.         CurrentInputIndex --;
  295.         OnError("Could not open verbatiminput file.");
  296.       }
  297.       else
  298.       {
  299.         readingVerbatim = TRUE;
  300.         readInVerbatim = TRUE;
  301.         strcpy(buf, "\\begin{verbatim}\n");
  302.         return FALSE;
  303.       }
  304.     }
  305.     return FALSE;
  306.   }
  307.   else if (strncmp(buf, "\\input", 6) == 0 || strncmp(buf, "\\helpinput", 10) == 0 ||
  308.       strncmp(buf, "\\include", 8) == 0)
  309.   {
  310.     int wordLen;
  311.     if (strncmp(buf, "\\input", 6) == 0)
  312.       wordLen = 6;
  313.     else
  314.     if (strncmp(buf, "\\include", 8) == 0)
  315.       wordLen = 8;
  316.     else
  317.       wordLen = 10;
  318.  
  319.     char *fileName = buf + wordLen + 1;
  320.  
  321.     int j = i - 1;
  322.     buf[j] = 0;
  323.  
  324.     // \input{thing}\par -- eliminate the \par!
  325.     if (strncmp((buf + strlen(buf)-5), "\\par", 4) == 0)
  326.     {
  327.       j -= 5;
  328.       buf[j] = 0;
  329.     }
  330.  
  331.     if (buf[j-1] == '}') buf[j-1] = 0; // Ignore final brace
  332.  
  333.     // Ignore some types of input files (e.g. macro definition files)
  334.     char *fileOnly = FileNameFromPath(fileName);
  335.     if (IgnorableInputFiles.Member(fileOnly))
  336.       return read_a_line(buf);
  337.  
  338.     char *actualFile = TexPathList.FindValidPath(fileName);
  339.     if (!actualFile)
  340.     {
  341.       char errBuf[300];
  342.       strcpy(errBuf, "Could not find file: ");
  343.       strncat(errBuf, fileName, 100);
  344.       OnError(errBuf);
  345.     }
  346.     else
  347.     {
  348.       CurrentInputIndex ++;
  349.       Inputs[CurrentInputIndex] = fopen(actualFile, "r");
  350.       if (!Inputs[CurrentInputIndex])
  351.       {
  352.         CurrentInputIndex --;
  353.         OnError("Could not open include file.");
  354.       }
  355.     }
  356.     Bool succ = read_a_line(buf);
  357.     return succ;
  358.   }
  359.   if (strncmp(buf, "\\begin{verbatim}", 16) == 0)
  360.     readInVerbatim = TRUE;
  361.   else if (strncmp(buf, "\\end{verbatim}", 14) == 0)
  362.     readInVerbatim = FALSE;
  363.  
  364.   return (ch == EOF);
  365. }
  366.  
  367. /*
  368.  * Parse newcommand
  369.  *
  370.  */
  371.  
  372. Bool ParseNewCommand(char *buffer, int *pos)
  373. {
  374.   if (strncmp((buffer+(*pos)), "newcommand", 10) == 0)
  375.   {
  376.     *pos = *pos + 12;
  377.     char commandName[100];
  378.     char commandValue[1000];
  379.     int noArgs = 0;
  380.     int i = 0;
  381.     while (buffer[*pos] != '}' && (buffer[*pos] != 0))
  382.     {
  383.       commandName[i] = buffer[*pos];
  384.       *pos += 1;
  385.       i ++;
  386.     }
  387.     commandName[i] = 0;
  388.     i = 0;
  389.     *pos += 1;
  390.     if (buffer[*pos] == '[')
  391.     {
  392.       *pos += 1;
  393.       noArgs = (int)(buffer[*pos]) - 48;
  394.       *pos += 1;
  395.     }
  396.     Bool end = FALSE;
  397.     Bool braceCount = 0;
  398.     while (!end)
  399.     {
  400.       char ch = buffer[*pos];
  401.       if (ch == '{')
  402.         braceCount ++;
  403.       else if (ch == '}')
  404.       {
  405.         braceCount --;
  406.         if (braceCount == 0)
  407.           end = TRUE;
  408.       }
  409.       else if (ch == 0)
  410.       {
  411.         if (!read_a_line(buffer))
  412.           end = TRUE;
  413.         *pos = 0;
  414.         break;
  415.       }
  416.       commandValue[i] = ch;
  417.       i ++;
  418.       *pos += 1;
  419.     }
  420.     commandValue[i] = 0;
  421.  
  422.     CustomMacro *macro = new CustomMacro(commandName, noArgs, NULL);
  423.     if (strlen(commandValue) > 0)
  424.       macro->macroBody = copystring(commandValue);
  425.     if (!CustomMacroList.Find(commandName))
  426.     {
  427.       CustomMacroList.Append(commandName, macro);
  428.       AddMacroDef(commandName, noArgs);
  429.     }
  430.     return TRUE;
  431.   }
  432.   else return FALSE;
  433. }
  434.  
  435. void MacroError(char *buffer)
  436. {
  437.   char errBuf[300];
  438.   char macroBuf[200];
  439.   strcpy(errBuf, "Could not find macro: ");
  440.   macroBuf[0] = '\\';
  441.   int i = 1;
  442.   char ch;
  443.   while (((ch = buffer[i-1]) != '\n') && (ch != 0))
  444.   {
  445.     macroBuf[i] = ch;
  446.     i ++;
  447.   }
  448.   macroBuf[i] = 0;
  449.   if (i > 20)
  450.     macroBuf[20] = 0;
  451.     
  452.   strcat(errBuf, macroBuf);
  453.   OnError(errBuf);
  454. }
  455.  
  456. /*
  457.  * Parse an argument.
  458.  * 'environment' specifies the name of the macro IFF if we're looking for the end
  459.  * of an environment, e.g. \end{itemize}. Otherwise it's NULL.
  460.  * 'parseToBrace' is TRUE if the argument should extend to the next right brace,
  461.  * e.g. in {\bf an argument} as opposed to \vskip 30pt
  462.  *
  463.  */
  464. int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *environment, Bool parseToBrace, TexChunk *customMacroArgs)
  465. {
  466.   Bool eof = FALSE;
  467.   BigBuffer[0] = 0;
  468.   int buf_ptr = 0;
  469.   int len;
  470.  
  471.   Bool isOptional = FALSE;
  472.  
  473.   // Consume leading brace or square bracket, but ONLY if not following
  474.   // a space, because this could be e.g. {\large {\bf thing}} where {\bf thing}
  475.   // is the argument of \large AS WELL as being a block in its
  476.   // own right.
  477.   if (!environment)
  478.   {
  479.     if ((pos > 0) && (buffer[pos-1] != ' ') && buffer[pos] == '{')
  480.       pos ++;
  481.     else if ((pos > 0) && (buffer[pos-1] != ' ') && (buffer[pos] == '[' || buffer[pos] == '('))
  482.     {
  483.       isOptional = TRUE;
  484.       pos ++;
  485.     }
  486.     else if ((pos > 1) && (buffer[pos-1] != ' ') && (buffer[pos+1] == '[' || buffer[pos+1] == '('))
  487.     {
  488.       isOptional = TRUE;
  489.       pos += 2;
  490.     }
  491.   }
  492.     
  493.   // If not parsing to brace, just read the next word
  494.   // (e.g. \vskip 20pt)
  495.   if (!parseToBrace)
  496.   {
  497.     int ch = buffer[pos];
  498.     while (!eof && ch != 13 && ch != 32 && ch != 10 &&
  499.            ch != 0 && ch != '(' && ch != '{')
  500.     {
  501.       BigBuffer[buf_ptr] = ch;
  502.       buf_ptr ++;
  503.       pos ++;
  504.       ch = buffer[pos];
  505.     }
  506.     if (buf_ptr > 0)
  507.     {
  508.       TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  509.       BigBuffer[buf_ptr] = 0;
  510.       buf_ptr = 0;
  511.       chunk->value = copystring(BigBuffer);
  512.       children.Append(chunk);
  513.     }
  514.     return pos;
  515.   }
  516.  
  517.   while (!eof)
  518.   {
  519.     len = strlen(buffer);
  520.     if (pos >= len)
  521.     {
  522.       eof = read_a_line(buffer);
  523.       pos = 0;
  524.       len = strlen(buffer);
  525.       // Check for verbatim
  526.       if (strncmp(buffer, "\\begin{verbatim}", 16) == 0)
  527.       {
  528.         if (buf_ptr > 0)
  529.         {
  530.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  531.           BigBuffer[buf_ptr] = 0;
  532.           buf_ptr = 0;
  533.           chunk->value = copystring(BigBuffer);
  534.           children.Append(chunk);
  535.         }
  536.         BigBuffer[0] = 0;
  537.         buf_ptr = 0;
  538.  
  539.         eof = read_a_line(buffer);
  540.         while (!eof && (strncmp(buffer, "\\end{verbatim}", 14) != 0))
  541.     {
  542.           strcat(BigBuffer, buffer);
  543.           buf_ptr += strlen(buffer);
  544.           eof = read_a_line(buffer);
  545.     }
  546.         eof = read_a_line(buffer);
  547.         buf_ptr = 0;
  548.  
  549.         TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  550.         chunk->no_args = 1;
  551.         chunk->name = copystring("verbatim");
  552.         TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG);
  553.         arg->argn = 1;
  554.         arg->name = copystring("verbatim");
  555.         TexChunk *str = new TexChunk(CHUNK_TYPE_STRING);
  556.         str->value = copystring(BigBuffer);
  557.  
  558.         children.Append(chunk);
  559.         chunk->children.Append(arg);
  560.         arg->children.Append(str);
  561.       }
  562.     }
  563.  
  564.     char ch = buffer[pos];
  565.     // End of optional argument -- pretend it's right brace for simplicity
  566.     if (isOptional && (ch == ']' || ch == ')'))
  567.       ch = '}';
  568.  
  569.     switch (ch)
  570.     {
  571.       case 0:
  572.       case '}':  // End of argument
  573.       {
  574.         if (buf_ptr > 0)
  575.         {
  576.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  577.           BigBuffer[buf_ptr] = 0;
  578.           buf_ptr = 0;
  579.           chunk->value = copystring(BigBuffer);
  580.           thisArg->optional = isOptional;
  581.           children.Append(chunk);
  582.         }
  583.         if (ch == '}') pos ++;
  584.         return pos;
  585.         break;
  586.       }
  587.       case '\\':
  588.       {
  589.         if (buf_ptr > 0)  // Finish off the string we've read so far
  590.         {
  591.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  592.           BigBuffer[buf_ptr] = 0;
  593.           buf_ptr = 0;
  594.           chunk->value = copystring(BigBuffer);
  595.           children.Append(chunk);
  596.         }
  597.         pos ++;
  598.  
  599.         // Try matching \end{environment}
  600.         if (environment && FindEndEnvironment(buffer, &pos, environment))
  601.         {
  602.           // Eliminate newline after an \end{} if possible
  603.           if (buffer[pos] == 13)
  604.           {
  605.             pos ++;
  606.             if (buffer[pos] == 10)
  607.               pos ++;
  608.           }
  609.           return pos;
  610.         }
  611.  
  612.         if (ParseNewCommand(buffer, &pos))
  613.           break;
  614.       
  615.         char *env = NULL;
  616.         Bool tmpParseToBrace = TRUE;
  617.         TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace);
  618.         if (def)
  619.         {
  620.           CustomMacro *customMacro = FindCustomMacro(def->name);
  621.  
  622.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  623.           chunk->no_args = def->no_args;
  624.           chunk->name = copystring(def->name);
  625.           if  (!customMacro)
  626.             children.Append(chunk);
  627.  
  628.           // Eliminate newline after a \begin{} or a \\ if possible
  629.           if (env || strcmp(def->name, "\\") == 0)
  630.             if (buffer[pos] == 13)
  631.             {
  632.               pos ++;
  633.               if (buffer[pos] == 10)
  634.                 pos ++;
  635.             }
  636.  
  637.           pos = ParseMacroBody(chunk->name, chunk, chunk->no_args,
  638.                      buffer, pos, env, tmpParseToBrace, customMacroArgs);
  639.  
  640.           // If custom macro, parse the body substituting the above found args.
  641.           if (customMacro)
  642.           {
  643.             if (customMacro->macroBody)
  644.             {
  645.               char macroBuf[300];
  646. //              strcpy(macroBuf, "{");
  647.               strcpy(macroBuf, customMacro->macroBody);
  648.               strcat(macroBuf, "}");
  649.               ParseArg(thisArg, children, macroBuf, 0, NULL, TRUE, chunk);
  650.             }
  651.             
  652. //            delete chunk; // Might delete children
  653.           }
  654.         }
  655.         else
  656.         {
  657.           MacroError(buffer+pos);
  658.         }
  659.         break;
  660.       }
  661.       // Parse constructs like {\bf thing} as if they were
  662.       // \bf{thing}
  663.       case '{':
  664.       {
  665.         pos ++;
  666.         if (buffer[pos] == '\\')
  667.         {
  668.           if (buf_ptr > 0)
  669.           {
  670.             TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  671.             BigBuffer[buf_ptr] = 0;
  672.             buf_ptr = 0;
  673.             chunk->value = copystring(BigBuffer);
  674.             children.Append(chunk);
  675.           }
  676.           pos ++;
  677.  
  678.           char *env;
  679.           Bool tmpParseToBrace;
  680.           TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace);
  681.           if (def)
  682.           {
  683.             CustomMacro *customMacro = FindCustomMacro(def->name);
  684.  
  685.             TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  686.             chunk->no_args = def->no_args;
  687.             chunk->name = copystring(def->name);
  688.             if (!customMacro)
  689.               children.Append(chunk);
  690.  
  691.             pos = ParseMacroBody(chunk->name, chunk, chunk->no_args,
  692.                        buffer, pos, NULL, TRUE, customMacroArgs);
  693.  
  694.             // If custom macro, parse the body substituting the above found args.
  695.             if (customMacro)
  696.             {
  697.               if (customMacro->macroBody)
  698.               {
  699.                 char macroBuf[300];
  700. //                strcpy(macroBuf, "{");
  701.                 strcpy(macroBuf, customMacro->macroBody);
  702.                 strcat(macroBuf, "}");
  703.                 ParseArg(thisArg, children, macroBuf, 0, NULL, TRUE, chunk);
  704.               }
  705.             
  706. //            delete chunk; // Might delete children
  707.         }
  708.           }
  709.           else
  710.           {
  711.             MacroError(buffer+pos);
  712.           }
  713.         }
  714.         else
  715.     {
  716.          /*
  717.           * If all else fails, we assume that we have
  718.           * a pair of braces on their own, so return a `dummy' macro
  719.           * definition with just one argument to parse.
  720.           */
  721.           if (!SoloBlockDef)
  722.           {
  723.             SoloBlockDef = new TexMacroDef("solo block", 1, FALSE);
  724.           }
  725.           // Save text so far
  726.           if (buf_ptr > 0)
  727.           {
  728.             TexChunk *chunk1 = new TexChunk(CHUNK_TYPE_STRING);
  729.             BigBuffer[buf_ptr] = 0;
  730.             buf_ptr = 0;
  731.             chunk1->value = copystring(BigBuffer);
  732.             children.Append(chunk1);
  733.           }
  734.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  735.           chunk->no_args = SoloBlockDef->no_args;
  736.           chunk->name = copystring(SoloBlockDef->name);
  737.           children.Append(chunk);
  738.           pos = ParseMacroBody(chunk->name, chunk, chunk->no_args,
  739.                        buffer, pos, NULL, TRUE, customMacroArgs);
  740.     }
  741.         break;
  742.       }
  743.       case '$':
  744.       {
  745.         if (buf_ptr > 0)
  746.         {
  747.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  748.           BigBuffer[buf_ptr] = 0;
  749.           buf_ptr = 0;
  750.           chunk->value = copystring(BigBuffer);
  751.           children.Append(chunk);
  752.         }
  753.  
  754.         pos ++;
  755.  
  756.         if (buffer[pos] == '$')
  757.         {
  758.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  759.           chunk->no_args = 0;
  760.           chunk->name = copystring("$$");
  761.           children.Append(chunk);
  762.           pos ++;
  763.         }
  764.         else
  765.         {
  766.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  767.           chunk->no_args = 0;
  768.           chunk->name = copystring("_$");
  769.           children.Append(chunk);
  770.         }
  771.         break;
  772.       }
  773.       case '~':
  774.       {
  775.         if (buf_ptr > 0)
  776.         {
  777.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  778.           BigBuffer[buf_ptr] = 0;
  779.           buf_ptr = 0;
  780.           chunk->value = copystring(BigBuffer);
  781.           children.Append(chunk);
  782.         }
  783.  
  784.         pos ++;
  785.         TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  786.         chunk->no_args = 0;
  787.         chunk->name = copystring("_~");
  788.         children.Append(chunk);
  789.         break;
  790.       }
  791.       case '#': // Either treat as a special TeX character or as a macro arg
  792.       {
  793.         if (buf_ptr > 0)
  794.         {
  795.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  796.           BigBuffer[buf_ptr] = 0;
  797.           buf_ptr = 0;
  798.           chunk->value = copystring(BigBuffer);
  799.           children.Append(chunk);
  800.         }
  801.  
  802.         pos ++;
  803.         if (!customMacroArgs)
  804.         {
  805.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  806.           chunk->no_args = 0;
  807.           chunk->name = copystring("_#");
  808.           children.Append(chunk);
  809.         }
  810.         else
  811.         {
  812.           if (isdigit(buffer[pos]))
  813.           {
  814.             int n = buffer[pos] - 48;
  815.             pos ++;
  816.             wxNode *node = customMacroArgs->children.Nth(n-1);
  817.             if (node)
  818.             {
  819.               TexChunk *argChunk = (TexChunk *)node->Data();
  820.               children.Append(new TexChunk(*argChunk));
  821.             }
  822.           }
  823.         }
  824.         break;
  825.       }
  826.       case '&':
  827.       {
  828.         // Remove white space before and after the ampersand,
  829.         // since this is probably a table column separator with
  830.         // some convenient -- but useless -- white space in the text.
  831.         while ((buf_ptr > 0) && ((BigBuffer[buf_ptr-1] == ' ') || (BigBuffer[buf_ptr-1] == 9)))
  832.           buf_ptr --;
  833.  
  834.         if (buf_ptr > 0)
  835.         {
  836.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  837.           BigBuffer[buf_ptr] = 0;
  838.           buf_ptr = 0;
  839.           chunk->value = copystring(BigBuffer);
  840.           children.Append(chunk);
  841.         }
  842.  
  843.         pos ++;
  844.  
  845.         while (buffer[pos] == ' ' || buffer[pos] == 9)
  846.           pos ++;
  847.  
  848.         TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  849.         chunk->no_args = 0;
  850.         chunk->name = copystring("_&");
  851.         children.Append(chunk);
  852.         break;
  853.       }
  854.       // Eliminate end-of-line comment
  855.       case '%':
  856.       {
  857.         ch = buffer[pos];
  858.         while (ch != 10 && ch != 13 && ch != 0)
  859.         {
  860.           pos ++;
  861.           ch = buffer[pos];
  862.         }
  863.         if (buffer[pos] == 10 || buffer[pos] == 13)
  864.         {
  865.           pos ++;
  866.           if (buffer[pos] == 10) pos ++; // Eliminate newline following DOS line feed
  867.         }
  868.         break;
  869.       }
  870.       // Eliminate tab
  871.       case 9:
  872.       {
  873.         BigBuffer[buf_ptr] = ' ';
  874.         BigBuffer[buf_ptr+1] = 0;
  875.         buf_ptr ++;
  876.         pos ++;
  877.         break;
  878.       }
  879.       default:
  880.       {
  881.         BigBuffer[buf_ptr] = ch;
  882.         BigBuffer[buf_ptr+1] = 0;
  883.         buf_ptr ++;
  884.         pos ++;
  885.         break;
  886.       }
  887.     }
  888.   }
  889.   return pos;
  890. }
  891.  
  892. /*
  893.  * Consume as many arguments as the macro definition specifies
  894.  *
  895.  */
  896.  
  897. int ParseMacroBody(char *macro_name, TexChunk *parent,
  898.                    int no_args, char *buffer, int pos,
  899.                    char *environment, Bool parseToBrace,
  900.                    TexChunk *customMacroArgs)
  901. {
  902.   // Check for a first optional argument
  903.   if (buffer[pos] == '[')
  904.     no_args ++;
  905.  
  906.   int maxArgs = 0;
  907.  
  908.   for (int i = 0; i < no_args; i++)
  909.   {
  910.     maxArgs ++;
  911.     TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG);
  912.  
  913.     parent->children.Append(arg);
  914.     arg->name = copystring(macro_name);
  915.     arg->argn = maxArgs;
  916.  
  917.     // To parse the first arg of a 2 arg \begin{thing}{arg} ... \end{thing}
  918.     // have to fool parser into thinking this is a regular kind of block.
  919.     char *actualEnv;
  920.     if ((no_args == 2) && (i == 0))
  921.       actualEnv = NULL;
  922.     else
  923.       actualEnv = environment;
  924.  
  925.     pos = ParseArg(arg, arg->children, buffer, pos, actualEnv, parseToBrace, customMacroArgs);
  926.  
  927.     // If we've encountered an OPTIONAL argument, go another time around
  928.     // the loop, because we've got more than we thought.
  929.     // Hopefully optional args don't occur at the end of a macro use
  930.     // or we might miss it.
  931.     // Don't increment no of times round loop if the first optional arg
  932.     // -- we already did it before the loop.
  933.     if (arg->optional && (i > 0))
  934.       i --;
  935.   }
  936.   parent->no_args = maxArgs;
  937.  
  938.   // Tell each argument how many args there are (useful when processing an arg)
  939.   wxNode *node = parent->children.First();
  940.   while (node)
  941.   {
  942.     TexChunk *chunk = (TexChunk *)node->Data();
  943.     chunk->no_args = maxArgs;
  944.     node = node->Next();
  945.   }
  946.   return pos;
  947. }
  948.  
  949. Bool TexLoadFile(char *filename, char *customMacroFile)
  950. {
  951.   strcpy(TexFileRoot, filename);
  952.   StripExtension(TexFileRoot);
  953.   sprintf(TexBibName, "%s.bb", TexFileRoot);
  954.   sprintf(TexTmpBibName, "%s.bb1", TexFileRoot);
  955.  
  956.   TexPathList.EnsureFileAccessible(filename);
  957.  
  958. #ifdef wx_msw
  959.   TexPathList.AddEnvList("TEXINPUT");
  960. #endif
  961. #ifdef wx_x
  962.   TexPathList.AddEnvList("TEXINPUTS");
  963. #endif
  964.   if (!customMacroFile)
  965.     customMacroFile = "tex2rtf.ini";
  966.   if (TexPathList.FindValidPath(customMacroFile))
  967.     ReadCustomMacros(customMacroFile);
  968.  
  969.   static char line_buffer[500];
  970.   Inputs[0] = fopen(filename, "r");
  971.   if (Inputs[0])
  972.   {
  973.     read_a_line(line_buffer);
  974.     ParseMacroBody("toplevel", TopLevel, 1, line_buffer, 0, NULL, TRUE);
  975.     if (Inputs[0]) fclose(Inputs[0]);
  976.     return TRUE;
  977.   }
  978.   else return FALSE;
  979. }
  980.  
  981. TexMacroDef::TexMacroDef(char *the_name, int n, Bool ig)
  982. {
  983.   name = copystring(the_name);
  984.   no_args = n;
  985.   ignore = ig;
  986. }
  987.  
  988. TexMacroDef::~TexMacroDef(void)
  989. {
  990.   if (name) delete[] name;
  991. }
  992.  
  993. TexChunk::TexChunk(int the_type)
  994. {
  995.   type = the_type;
  996.   no_args = 0;
  997.   argn = 0;
  998.   name = NULL;
  999.   value = NULL;
  1000.   optional = FALSE;
  1001.   children.DeleteContents(TRUE);
  1002. }
  1003.  
  1004. TexChunk::TexChunk(TexChunk& toCopy)
  1005. {
  1006.   type = toCopy.type;
  1007.   no_args = toCopy.no_args;
  1008.   argn = toCopy.argn;
  1009.   if (toCopy.name)
  1010.     name = copystring(toCopy.name);
  1011.   else
  1012.     name = NULL;
  1013.  
  1014.   if (toCopy.value)
  1015.     value = copystring(toCopy.value);
  1016.   else
  1017.     value = NULL;
  1018.   
  1019.   optional = toCopy.optional;
  1020.   wxNode *node = toCopy.children.First();
  1021.   while (node)
  1022.   {
  1023.     TexChunk *child = (TexChunk *)node->Data();
  1024.     children.Append(new TexChunk(*child));
  1025.     node = node->Next();
  1026.   }
  1027.   children.DeleteContents(TRUE);
  1028. }
  1029.  
  1030. TexChunk::~TexChunk(void)
  1031. {
  1032.   if (name) delete[] name;
  1033.   if (value) delete[] value;
  1034. }
  1035.  
  1036. Bool IsArgOptional(void)  // Is this argument an optional argument?
  1037. {
  1038.   return isArgOptional;
  1039. }
  1040.  
  1041. int GetNoArgs(void) // Number of args for this macro
  1042. {
  1043.   return noArgs;
  1044. }
  1045.  
  1046. /* Gets the text of a chunk on request (must be for small arguments
  1047.  * only!)
  1048.  *
  1049.  */
  1050.  
  1051. void GetArgData1(TexChunk *chunk)
  1052. {
  1053.   switch (chunk->type)
  1054.   {
  1055.     case CHUNK_TYPE_MACRO:
  1056.     {
  1057.       wxNode *node = MacroDefs.Find(chunk->name);
  1058.       if (node)
  1059.       {
  1060.         TexMacroDef *def = (TexMacroDef *)node->Data();
  1061.         if (def->ignore)
  1062.           return;
  1063.       }
  1064.  
  1065.       strcat(currentArgData, "\\");
  1066.       strcat(currentArgData, chunk->name);
  1067.  
  1068.       node = chunk->children.First();
  1069.       while (node)
  1070.       {
  1071.         TexChunk *child_chunk = (TexChunk *)node->Data();
  1072.         strcat(currentArgData, "{");
  1073.         GetArgData1(child_chunk);
  1074.         strcat(currentArgData, "}");
  1075.         node = node->Next();
  1076.       }
  1077.       break;
  1078.     }
  1079.     case CHUNK_TYPE_ARG:
  1080.     {
  1081.       wxNode *node = chunk->children.First();
  1082.       while (node)
  1083.       {
  1084.         TexChunk *child_chunk = (TexChunk *)node->Data();
  1085.         GetArgData1(child_chunk);
  1086.         node = node->Next();
  1087.       }
  1088.       break;
  1089.     }
  1090.     case CHUNK_TYPE_STRING:
  1091.     {
  1092.       if (chunk->value)
  1093.         strcat(currentArgData, chunk->value);
  1094.       break;
  1095.     }
  1096.   }
  1097. }
  1098.  
  1099. char *GetArgData(void)
  1100. {
  1101.   if (!haveArgData)
  1102.   {
  1103.     currentArgData[0] = 0;
  1104.     GetArgData1(currentArgument);
  1105.   }
  1106.   return currentArgData;
  1107. }
  1108.  
  1109. TexChunk *GetArgChunk(void)
  1110. {
  1111.   return currentArgument;
  1112. }
  1113.  
  1114. TexChunk *GetNextChunk(void)     // Look ahead to the next chunk
  1115. {
  1116.   return nextChunk;
  1117. }
  1118.  
  1119. TexChunk *GetTopLevelChunk(void)
  1120. {
  1121.   return TopLevel;
  1122. }
  1123.  
  1124. int GetCurrentColumn(void)
  1125. {
  1126.   return currentColumn;
  1127. }
  1128.  
  1129. /*
  1130.  * Traverses document calling functions to allow the client to
  1131.  * write out the appropriate stuff
  1132.  */
  1133.  
  1134.  
  1135. void TraverseFromChunk(TexChunk *chunk, wxNode *thisNode, Bool childrenOnly)
  1136. {
  1137.   switch (chunk->type)
  1138.   {
  1139.     case CHUNK_TYPE_MACRO:
  1140.     {
  1141.       wxNode *node = MacroDefs.Find(chunk->name);
  1142.       if (node)
  1143.       {
  1144.         TexMacroDef *def = (TexMacroDef *)node->Data();
  1145.         if (def->ignore)
  1146.           return;
  1147.       }
  1148.  
  1149.       if (!childrenOnly)
  1150.         OnMacro(chunk->name, chunk->no_args, TRUE);
  1151.  
  1152.       node = chunk->children.First();
  1153.       while (node)
  1154.       {
  1155.         TexChunk *child_chunk = (TexChunk *)node->Data();
  1156.         TraverseFromChunk(child_chunk, node);
  1157.         node = node->Next();
  1158.       }
  1159.  
  1160.       if (thisNode && thisNode->Next()) nextChunk = (TexChunk *)thisNode->Next()->Data();
  1161.  
  1162.       if (!childrenOnly)
  1163.         OnMacro(chunk->name, chunk->no_args, FALSE);
  1164.       break;
  1165.     }
  1166.     case CHUNK_TYPE_ARG:
  1167.     {
  1168.       currentArgument = chunk;
  1169.  
  1170.       isArgOptional = chunk->optional;
  1171.       noArgs = chunk->no_args;
  1172.  
  1173.       // If OnArgument returns FALSE, don't output.
  1174.  
  1175.       if (childrenOnly || OnArgument(chunk->name, chunk->argn, TRUE))
  1176.       {
  1177.         wxNode *node = chunk->children.First();
  1178.         while (node)
  1179.         {
  1180.           TexChunk *child_chunk = (TexChunk *)node->Data();
  1181.           TraverseFromChunk(child_chunk, node);
  1182.           node = node->Next();
  1183.         }
  1184.       }
  1185.  
  1186.       currentArgument = chunk;
  1187.  
  1188.       if (thisNode && thisNode->Next()) nextChunk = (TexChunk *)thisNode->Next()->Data();
  1189.  
  1190.       isArgOptional = chunk->optional;
  1191.       noArgs = chunk->no_args;
  1192.  
  1193.       if (!childrenOnly)
  1194.         (void)OnArgument(chunk->name, chunk->argn, FALSE);
  1195.       break;
  1196.     }
  1197.     case CHUNK_TYPE_STRING:
  1198.     {
  1199.       if (chunk->value)
  1200.         TexOutput(chunk->value, TRUE);
  1201.       break;
  1202.     }
  1203.   }
  1204. }
  1205.  
  1206. void TraverseDocument(void)
  1207. {
  1208.   TraverseFromChunk(TopLevel, NULL);
  1209. }
  1210.  
  1211. void SetCurrentOutput(FILE *fd)
  1212. {
  1213.   CurrentOutput1 = fd;
  1214.   CurrentOutput2 = NULL;
  1215. }
  1216.  
  1217. void SetCurrentOutputs(FILE *fd1, FILE *fd2)
  1218. {
  1219.   CurrentOutput1 = fd1;
  1220.   CurrentOutput2 = fd2;
  1221. }
  1222.  
  1223. void AddMacroDef(char *name, int n, Bool ignore)
  1224. {
  1225.   MacroDefs.Append(name, new TexMacroDef(name, n, ignore));
  1226. }
  1227.  
  1228. void TexInitialize(void)
  1229. {
  1230.   for (int i = 0; i < 15; i++)
  1231.     Inputs[i] = NULL;
  1232.  
  1233.   IgnorableInputFiles.Add("psbox.tex");
  1234.   BigBuffer = new char[20000];
  1235.   AddMacroDef("toplevel", 1);
  1236.   TopLevel = new TexChunk(CHUNK_TYPE_MACRO);
  1237.   TopLevel->name = copystring("toplevel");
  1238.   TopLevel->no_args = 1;
  1239. }
  1240.  
  1241. void TexCleanUp(void)
  1242. {
  1243.   for (int i = 0; i < 15; i++)
  1244.     Inputs[i] = NULL;
  1245.  
  1246.   chapterNo = 0;
  1247.   sectionNo = 0;
  1248.   subsectionNo = 0;
  1249.   subsubsectionNo = 0;
  1250.   figureNo = 0;
  1251.  
  1252.   CurrentOutput1 = NULL;
  1253.   CurrentOutput2 = NULL;
  1254.   CurrentInputIndex = 0;
  1255.   haveArgData = FALSE;
  1256.   noArgs = 0;
  1257.  
  1258.   if (TopLevel)
  1259.     delete TopLevel;
  1260.   TopLevel = new TexChunk(CHUNK_TYPE_MACRO);
  1261.   TopLevel->name = copystring("toplevel");
  1262.   TopLevel->no_args = 1;
  1263.  
  1264.   DocumentTitle = NULL;
  1265.   DocumentAuthor = NULL;
  1266.   DocumentDate = NULL;
  1267.   CurrentLabel = NULL;
  1268.   DocumentStyle = LATEX_REPORT;
  1269.   MinorDocumentStyle = 0;
  1270.   BibliographyStyleString = copystring("plain");
  1271.   DocumentStyleString = copystring("report");
  1272.   SetFontSizes(10);
  1273.   wxNode *node = CustomMacroList.First();
  1274.   while (node)
  1275.   {
  1276.     CustomMacro *macro = (CustomMacro *)node->Data();
  1277.     delete macro;
  1278.     delete node;
  1279.     node = CustomMacroList.First();
  1280.   }
  1281.   node = TexReferences.First();
  1282.   while (node)
  1283.   {
  1284.     TexRef *ref = (TexRef *)node->Data();
  1285.     delete ref;
  1286.     delete node;
  1287.     node = TexReferences.First();
  1288.   }
  1289.   node = BibList.First();
  1290.   while (node)
  1291.   {
  1292.     BibEntry *entry = (BibEntry *)node->Data();
  1293.     delete entry;
  1294.     delete node;
  1295.     node = BibList.First();
  1296.   }
  1297.   CitationList.Clear();
  1298.   ResetTopicCounter();
  1299. }
  1300.  
  1301. // There is likely to be one set of macros used by all utilities.
  1302. void DefineDefaultMacros(void)
  1303. {
  1304.   // Put names which subsume other names at the TOP
  1305.   // so they get recognized first
  1306.  
  1307.   AddMacroDef("abstract", 1);
  1308.   AddMacroDef("addcontentsline", 3);
  1309.   AddMacroDef("addtocounter", 2);
  1310.   AddMacroDef("alph", 1);
  1311.   AddMacroDef("Alph", 1);
  1312.   AddMacroDef("appendix", 0);
  1313.   AddMacroDef("arabic", 1);
  1314.   AddMacroDef("array", 1);
  1315.   AddMacroDef("author", 1);
  1316.  
  1317.   AddMacroDef("backslash", 0);
  1318.   AddMacroDef("baselineskip", 1);
  1319.   AddMacroDef("bf", 1);
  1320.   AddMacroDef("bibitem", 2);  // For convenience, bibitem has 2 args: label and item.
  1321.                               // The Latex syntax permits writing as 2 args.
  1322.   AddMacroDef("bibliographystyle", 1);
  1323.   AddMacroDef("bibliography", 1);
  1324.   AddMacroDef("boxit", 1);
  1325.  
  1326.   AddMacroDef("caption*", 1);
  1327.   AddMacroDef("caption", 1);
  1328.   AddMacroDef("cdots", 0);
  1329.   AddMacroDef("centerline", 1);
  1330.   AddMacroDef("centering", 0);
  1331.   AddMacroDef("center", 1);
  1332.   AddMacroDef("cextract", 0);
  1333.   AddMacroDef("chapter*", 1);
  1334.   AddMacroDef("chapter", 1);
  1335.   AddMacroDef("cinsert", 0);
  1336.   AddMacroDef("cite", 1);
  1337.   AddMacroDef("class", 1);
  1338.   AddMacroDef("cleardoublepage", 0);
  1339.   AddMacroDef("clearpage", 0);
  1340.   AddMacroDef("cline", 1);
  1341.   AddMacroDef("clipsfunc", 3);
  1342.   AddMacroDef("columnsep", 1);
  1343.   AddMacroDef("comment", 1, TRUE);
  1344.   AddMacroDef("copyright", 0);
  1345.   AddMacroDef("cparam", 2);
  1346.  
  1347.   AddMacroDef("date", 1);
  1348.   AddMacroDef("description", 1);
  1349.   AddMacroDef("destruct", 1);
  1350.   AddMacroDef("documentstyle", 1);
  1351.   AddMacroDef("document", 1);
  1352.   AddMacroDef("doublespace", 1);
  1353.  
  1354.   AddMacroDef("em", 1);
  1355.   AddMacroDef("enumerate", 1);
  1356.   AddMacroDef("equation", 1);
  1357.   AddMacroDef("evensidemargin", 1);
  1358.  
  1359.   AddMacroDef("fbox", 1);
  1360.   AddMacroDef("figure", 1);
  1361.   AddMacroDef("flushleft", 1);
  1362.   AddMacroDef("flushright", 1);
  1363.   AddMacroDef("footheight", 1);
  1364.   AddMacroDef("footnote", 1);
  1365.   AddMacroDef("footskip", 1);
  1366.   AddMacroDef("framebox", 1);
  1367.   AddMacroDef("functionsection", 1);
  1368.   AddMacroDef("func", 3);
  1369.  
  1370.   AddMacroDef("glossary", 1);
  1371.   AddMacroDef("gloss", 1);
  1372.  
  1373.   AddMacroDef("headheight", 1);
  1374.   AddMacroDef("helpignore", 1, TRUE);
  1375.   AddMacroDef("helponly", 1);
  1376.   AddMacroDef("helpinput", 1);
  1377.   AddMacroDef("helpfontfamily", 1);
  1378.   AddMacroDef("helpfontsize", 1);
  1379.   AddMacroDef("helprefn", 2);
  1380.   AddMacroDef("helpref", 2);
  1381.   AddMacroDef("hfill", 0);
  1382.   AddMacroDef("hline", 0);
  1383.   AddMacroDef("hrule", 0);
  1384.   AddMacroDef("hspace*", 1);
  1385.   AddMacroDef("hspace", 1);
  1386.   AddMacroDef("hskip*", 1);
  1387.   AddMacroDef("hskip", 1);
  1388.   AddMacroDef("huge", 1);
  1389.   AddMacroDef("Huge", 1);
  1390.   AddMacroDef("HUGE", 1);
  1391.  
  1392.   AddMacroDef("includeonly", 1);
  1393.   AddMacroDef("include", 1);
  1394.   AddMacroDef("index", 1);
  1395.   AddMacroDef("input", 1);
  1396.   AddMacroDef("itemize", 1);
  1397.   AddMacroDef("item", 0);
  1398.   AddMacroDef("image", 2);
  1399.   AddMacroDef("it", 1);
  1400.  
  1401.   AddMacroDef("kill", 0);
  1402.  
  1403.   AddMacroDef("label", 1);
  1404.   AddMacroDef("large", 1);
  1405.   AddMacroDef("Large", 1);
  1406.   AddMacroDef("LARGE", 1);
  1407.   AddMacroDef("LaTeX", 0);
  1408.   AddMacroDef("lbox", 1);
  1409.   AddMacroDef("ldots", 0);
  1410.   AddMacroDef("linebreak", 0);
  1411.   AddMacroDef("listoffigures", 0);
  1412.   AddMacroDef("listoftables", 0);
  1413.  
  1414.   AddMacroDef("makeglossary", 0);
  1415.   AddMacroDef("makeindex", 0);
  1416.   AddMacroDef("maketitle", 0);
  1417.   AddMacroDef("markright", 1);
  1418.   AddMacroDef("markboth", 2);
  1419.   AddMacroDef("marginparwidth", 1);
  1420.   AddMacroDef("marginpar", 1);
  1421.   AddMacroDef("mbox", 1);
  1422.   AddMacroDef("membersection", 1);
  1423.   AddMacroDef("member", 2);
  1424.   AddMacroDef("multicolumn", 3);
  1425.   AddMacroDef("myheading", 1);
  1426.  
  1427.   AddMacroDef("newcounter", 1);
  1428.   AddMacroDef("newline", 0);
  1429.   AddMacroDef("newpage", 0);
  1430.   AddMacroDef("nocite", 1);
  1431.   AddMacroDef("noindent", 0);
  1432.   AddMacroDef("nolinebreak", 0);
  1433.   AddMacroDef("nopagebreak", 0);
  1434.   AddMacroDef("normalsize", 1);
  1435.  
  1436.   AddMacroDef("onecolumn", 0);
  1437.   AddMacroDef("oddsidemargin", 1);
  1438.  
  1439.   AddMacroDef("pagebreak", 0);
  1440.   AddMacroDef("pageref", 1);
  1441.   AddMacroDef("pagestyle", 1);
  1442.   AddMacroDef("pagenumbering", 1);
  1443.   AddMacroDef("paragraph*", 1);
  1444.   AddMacroDef("paragraph", 1);
  1445.   AddMacroDef("param", 2);
  1446.   AddMacroDef("parindent", 1);
  1447.   AddMacroDef("parskip", 1);
  1448.   AddMacroDef("part*", 1);
  1449.   AddMacroDef("part", 1);
  1450.   AddMacroDef("par", 0);
  1451.   AddMacroDef("pfunc", 3);
  1452.   AddMacroDef("picture", 1);
  1453.   AddMacroDef("printindex", 0);
  1454.   AddMacroDef("psboxto", 1);
  1455.   AddMacroDef("psbox", 1);
  1456.  
  1457.   AddMacroDef("quote", 1);
  1458.   AddMacroDef("quotation", 1);
  1459.  
  1460.   AddMacroDef("raggedbottom", 0);
  1461.   AddMacroDef("raggedleft", 0);
  1462.   AddMacroDef("raggedright", 0);
  1463.   AddMacroDef("ref", 1);
  1464.   AddMacroDef("rm", 1);
  1465.   AddMacroDef("roman", 1);
  1466.   AddMacroDef("Roman", 1);
  1467. //  AddMacroDef("row", 1);
  1468.   AddMacroDef("rtfsp", 0);
  1469. //  AddMacroDef("ruledrow", 1);
  1470.  
  1471.   AddMacroDef("sc", 1);
  1472.   AddMacroDef("section*", 1);
  1473.   AddMacroDef("section", 1);
  1474.   AddMacroDef("setcounter", 2);
  1475.   AddMacroDef("sf", 1);
  1476.   AddMacroDef("shortcite", 1);
  1477.   AddMacroDef("singlespace", 1);
  1478.   AddMacroDef("sloppypar", 1);
  1479.   AddMacroDef("sloppy", 0);
  1480.   AddMacroDef("sl", 1);
  1481.   AddMacroDef("small", 1);
  1482.   AddMacroDef("subitem", 0);
  1483.   AddMacroDef("subparagraph*", 1);
  1484.   AddMacroDef("subparagraph", 1);
  1485.   AddMacroDef("special", 1);
  1486.   AddMacroDef("subsection*", 1);
  1487.   AddMacroDef("subsection", 1);
  1488.   AddMacroDef("subsubsection*", 1);
  1489.   AddMacroDef("subsubsection", 1);
  1490.  
  1491.   AddMacroDef("tabbing", 2);
  1492.   AddMacroDef("tableofcontents", 0);
  1493.   AddMacroDef("table", 1);
  1494.   AddMacroDef("tabular", 2);
  1495.   AddMacroDef("tab", 0);
  1496.   AddMacroDef("TeX", 0);
  1497.   AddMacroDef("textwidth", 1);
  1498.   AddMacroDef("textheight", 1);
  1499.   AddMacroDef("thebibliography", 2);
  1500.   AddMacroDef("titlepage", 1);
  1501.   AddMacroDef("title", 1);
  1502.   AddMacroDef("tiny", 1);
  1503.   AddMacroDef("today", 0);
  1504.   AddMacroDef("topmargin", 1);
  1505.   AddMacroDef("topskip", 1);
  1506.   AddMacroDef("tt", 1);
  1507.   AddMacroDef("typein", 1);
  1508.   AddMacroDef("typeout", 1);
  1509.   AddMacroDef("twocolumn", 0);
  1510.  
  1511.   AddMacroDef("underline", 1);
  1512.   
  1513.   AddMacroDef("vdots", 0);
  1514.   AddMacroDef("verbatiminput", 1);
  1515.   AddMacroDef("verbatim", 1);
  1516.   AddMacroDef("verb", 0);
  1517.   AddMacroDef("verse", 1);
  1518.   AddMacroDef("vfill", 0);
  1519.   AddMacroDef("vline", 0);
  1520.   AddMacroDef("void", 0);
  1521.   AddMacroDef("vrule", 0);
  1522.   AddMacroDef("vspace*", 1);
  1523.   AddMacroDef("vskip*", 1);
  1524.   AddMacroDef("vspace", 1);
  1525.   AddMacroDef("vskip", 1);
  1526.  
  1527.   AddMacroDef("wxclips", 0);
  1528.  
  1529.   AddMacroDef(" ", 0);
  1530.   AddMacroDef("\\", 0);
  1531.   AddMacroDef("|", 0);
  1532.   AddMacroDef("/", 0);
  1533.   AddMacroDef("_", 0);
  1534.   AddMacroDef("&", 0);
  1535.   AddMacroDef("%", 0);
  1536.   AddMacroDef("$", 0);
  1537.   AddMacroDef("#", 0);
  1538.   AddMacroDef("(", 0);
  1539.   AddMacroDef(")", 0);
  1540.   AddMacroDef("{", 0);
  1541.   AddMacroDef("}", 0);
  1542.   AddMacroDef("=", 0);
  1543.   AddMacroDef(">", 0);
  1544.   AddMacroDef("<", 0);
  1545.   AddMacroDef("+", 0);
  1546.   AddMacroDef("-", 0);
  1547.   AddMacroDef("'", 0);
  1548.   AddMacroDef("`", 0);
  1549. }
  1550.  
  1551. /*
  1552.  * Default behaviour, should be called by client if can't match locally.
  1553.  *
  1554.  */
  1555.  
  1556. // Called on start/end of macro examination
  1557. void DefaultOnMacro(char *name, int no_args, Bool start)
  1558. {
  1559.   // Default behaviour for abstract: should really do better than this.
  1560.   if (strcmp(name, "abstract") == 0)
  1561.   {
  1562.     if (start)
  1563.     {
  1564.       OnMacro("flushleft", 1, TRUE);
  1565.       OnArgument("flushleft", 1, TRUE);
  1566.         OnMacro("bf", 1, TRUE);
  1567.         OnArgument("bf", 1, TRUE);
  1568.           OnMacro("LARGE", 1, TRUE);
  1569.           OnArgument("LARGE", 1, TRUE);
  1570.             TexOutput("Abstract", TRUE);
  1571.           OnArgument("LARGE", 1, FALSE);
  1572.           OnMacro("LARGE", 1, FALSE);
  1573.         OnArgument("bf", 1, FALSE);
  1574.         OnMacro("bf", 1, FALSE);
  1575.       OnArgument("flushleft", 1, FALSE);
  1576.  
  1577.       OnMacro("par", 0, TRUE);
  1578.       OnMacro("par", 0, TRUE);
  1579.       OnMacro("par", 0, TRUE);
  1580.       OnMacro("par", 0, FALSE);
  1581.       OnMacro("par", 0, FALSE);
  1582.       OnMacro("par", 0, FALSE);
  1583.     }
  1584.   }
  1585.   else if ((strcmp(name, "cinsert") == 0) && start)
  1586.     TexOutput("<<", TRUE);
  1587.   else if ((strcmp(name, "cextract") == 0) && start)
  1588.     TexOutput(">>", TRUE);
  1589.   else if ((strcmp(name, "destruct") == 0) && start)
  1590.     TexOutput("~", TRUE);
  1591.   else if ((strcmp(name, "~") == 0) && start)
  1592.     TexOutput("~", TRUE);
  1593.   else if ((strcmp(name, "_~") == 0) && start)
  1594.     TexOutput(" ", TRUE);
  1595.   else if ((strcmp(name, ",") == 0) && start)
  1596.     TexOutput(" ", TRUE);
  1597.   else if ((strcmp(name, ":") == 0) && start)
  1598.     TexOutput(" ", TRUE);
  1599.   else if ((strcmp(name, ";") == 0) && start)
  1600.     TexOutput(" ", TRUE);
  1601.   else if ((strcmp(name, "!") == 0) && start)
  1602.     TexOutput(" ", TRUE);
  1603.   else if ((strcmp(name, "_") == 0) && start)
  1604.     TexOutput("_", TRUE);
  1605.   else if ((strcmp(name, "#") == 0) && start)
  1606.     TexOutput("#", TRUE);
  1607.   else if ((strcmp(name, "&") == 0) && start)
  1608.     TexOutput("&", TRUE);
  1609.   else if ((strcmp(name, " ") == 0) && start)
  1610.     TexOutput(" ", TRUE);
  1611.   else if ((strcmp(name, "|") == 0) && start)
  1612.     TexOutput("|", TRUE);
  1613.   else if ((strcmp(name, "%") == 0) && start)
  1614.     TexOutput("%", TRUE);
  1615.   else if ((strcmp(name, "$") == 0) && start)
  1616.     TexOutput("$", TRUE);
  1617.   else if ((strcmp(name, "(") == 0) && start)
  1618.     TexOutput("", TRUE);
  1619.   else if ((strcmp(name, ")") == 0) && start)
  1620.     TexOutput("", TRUE);
  1621.   else if ((strcmp(name, "{") == 0) && start)
  1622.     TexOutput("{", TRUE);
  1623.   else if ((strcmp(name, "}") == 0) && start)
  1624.     TexOutput("}", TRUE);
  1625.   else if ((strcmp(name, "copyright") == 0) && start)
  1626.     TexOutput("(c)", TRUE);
  1627.   else if ((strcmp(name, "backslash") == 0) && start)
  1628.     TexOutput("\\", TRUE);
  1629.   else if (start && (strcmp(name, "ldots") == 0 || strcmp(name, "cdots") == 0))
  1630.     TexOutput("...", TRUE);
  1631.   else if (start && (strcmp(name, "vdots") == 0))
  1632.     TexOutput("|", TRUE);
  1633.   else if ((strcmp(name, "LaTeX") == 0) && start)
  1634.     TexOutput("LaTeX", TRUE);
  1635.   else if ((strcmp(name, "TeX") == 0) && start)
  1636.     TexOutput("TeX", TRUE);
  1637.   else if ((strcmp(name, "pounds") == 0) && start)
  1638.     TexOutput("ú", TRUE);
  1639.   else if (strcmp(name, "sl") == 0)
  1640.   {
  1641.     OnMacro("it", no_args, start);
  1642.   }
  1643.   else if (strcmp(name, "today") == 0)
  1644.   {
  1645. #ifdef wx_x
  1646.     long when;
  1647. #endif
  1648. #ifdef wx_msw
  1649.     time_t when;
  1650. #endif
  1651.     (void) time(&when);
  1652.     TexOutput(ctime(&when), TRUE);
  1653.   }
  1654.   else if (strcmp(name, "noindent") == 0)
  1655.   {
  1656.     if (start)
  1657.       ParIndent = 0;
  1658.   }
  1659.   // Default way of writing the references title
  1660.   else if (strcmp(name, "references") == 0 && start)
  1661.   {
  1662.     OnMacro("flushleft", 1, TRUE);
  1663.     OnArgument("flushleft", 1, TRUE);
  1664.       OnMacro("LARGE", 1, TRUE);
  1665.       OnArgument("LARGE", 1, TRUE);
  1666.         OnMacro("bf", 1, TRUE);
  1667.         OnArgument("bf", 1, TRUE);
  1668.           TexOutput("References");
  1669.         OnArgument("bf", 1, FALSE);
  1670.         OnMacro("bf", 1, FALSE);
  1671.       OnArgument("LARGE", 1, FALSE);
  1672.       OnMacro("LARGE", 1, FALSE);
  1673.     OnArgument("flushleft", 1, FALSE);
  1674.     OnMacro("flushleft", 1, FALSE);
  1675.  
  1676.     OnMacro("par", 0, TRUE);
  1677.     OnMacro("par", 0, FALSE);
  1678.   }
  1679. }
  1680.  
  1681. // Called on start/end of argument examination
  1682. Bool DefaultOnArgument(char *macro_name, int arg_no, Bool start)
  1683. {
  1684.   if (strcmp(macro_name, "ref") == 0)
  1685.   {
  1686.     if (arg_no == 1 && start)
  1687.     {
  1688.       char *refName = GetArgData();
  1689.       if (refName)
  1690.       {
  1691.         wxNode *node = TexReferences.Find(refName);
  1692.         if (node)
  1693.         {
  1694.           TexRef *texRef = (TexRef *)node->Data();
  1695.  
  1696.           // Must strip the 'section' or 'chapter' or 'figure' text
  1697.           // from a normal 'ref' reference
  1698.           char buf[150];
  1699.           strcpy(buf, texRef->sectionNumber);
  1700.           int len = strlen(buf);
  1701.           int i = 0;
  1702.           if (strcmp(buf, "??") != 0)
  1703.           {
  1704.             while (i < len)
  1705.             {
  1706.               if (buf[i] == ' ')
  1707.               {
  1708.                 i ++;
  1709.                 break;
  1710.               }
  1711.               else i ++;
  1712.             }
  1713.           }
  1714.           TexOutput(texRef->sectionNumber + i, TRUE);
  1715.         }
  1716.         else
  1717.         {
  1718.           char buf[300];
  1719.           TexOutput("??", TRUE);
  1720.           sprintf(buf, "Warning: unresolved reference %s.", refName); 
  1721.           OnInform(buf);
  1722.         }
  1723.       }
  1724.       else TexOutput("??", TRUE);
  1725.       return FALSE;
  1726.     }
  1727.   }
  1728.   else if (strcmp(macro_name, "label") == 0)
  1729.   {
  1730.     if (start && (arg_no == 1))
  1731.     {
  1732.       if (CurrentLabel) delete CurrentLabel;
  1733.       CurrentLabel = copystring(GetArgData());
  1734.     }
  1735.     return FALSE;
  1736.   }
  1737.   else if (strcmp(macro_name, "author") == 0)
  1738.   {
  1739.     if (start && (arg_no == 1))
  1740.       DocumentAuthor = GetArgChunk();
  1741.     return FALSE;
  1742.   }
  1743.   else if (strcmp(macro_name, "date") == 0)
  1744.   {
  1745.     if (start && (arg_no == 1))
  1746.       DocumentDate = GetArgChunk();
  1747.     return FALSE;
  1748.   }
  1749.   else if (strcmp(macro_name, "title") == 0)
  1750.   {
  1751.     if (start && (arg_no == 1))
  1752.       DocumentTitle = GetArgChunk();
  1753.     return FALSE;
  1754.   }
  1755.   else if (strcmp(macro_name, "documentstyle") == 0)
  1756.   {
  1757.     if (start && !IsArgOptional())
  1758.     {
  1759.       DocumentStyleString = copystring(GetArgData());
  1760.       if (strncmp(DocumentStyleString, "art", 3) == 0)
  1761.         DocumentStyle = LATEX_ARTICLE;
  1762.       else if (strncmp(DocumentStyleString, "rep", 3) == 0)
  1763.         DocumentStyle = LATEX_REPORT;
  1764.       else if (strncmp(DocumentStyleString, "book", 4) == 0 ||
  1765.                strncmp(DocumentStyleString, "thesis", 6) == 0)
  1766.         DocumentStyle = LATEX_BOOK;
  1767.       else if (strncmp(DocumentStyleString, "letter", 6) == 0)
  1768.         DocumentStyle = LATEX_LETTER;
  1769.       else if (strncmp(DocumentStyleString, "slides", 6) == 0)
  1770.         DocumentStyle = LATEX_SLIDES;
  1771.         
  1772.       if (StringMatch("10", DocumentStyleString))
  1773.         SetFontSizes(10);
  1774.       else if (StringMatch("11", DocumentStyleString))
  1775.         SetFontSizes(11);
  1776.       else if (StringMatch("12", DocumentStyleString))
  1777.         SetFontSizes(12);
  1778.  
  1779.       OnMacro("helpfontsize", 1, TRUE);
  1780.       sprintf(currentArgData, "%d", normalFont);
  1781.       haveArgData = TRUE;
  1782.       OnArgument("helpfontsize", 1, TRUE);
  1783.       OnArgument("helpfontsize", 1, FALSE);
  1784.       haveArgData = FALSE;
  1785.       OnMacro("helpfontsize", 1, FALSE);
  1786.     }
  1787.     else if (start && IsArgOptional())
  1788.     {
  1789.       char *optionalStyle = copystring(GetArgData());
  1790.  
  1791.       if (StringMatch("10", optionalStyle))
  1792.         SetFontSizes(10);
  1793.       else if (StringMatch("11", optionalStyle))
  1794.         SetFontSizes(11);
  1795.       else if (StringMatch("12", optionalStyle))
  1796.         SetFontSizes(12);
  1797.     }
  1798.     return FALSE;
  1799.   }
  1800.   else if (strcmp(macro_name, "bibliographystyle") == 0)
  1801.   {
  1802.     if (start && !IsArgOptional())
  1803.       BibliographyStyleString = copystring(GetArgData());
  1804.     return FALSE;
  1805.   }
  1806.   else if (strcmp(macro_name, "cite") == 0 || strcmp(macro_name, "shortcite") == 0)
  1807.   {
  1808.     if (start && !IsArgOptional())
  1809.     {
  1810.       char *citeKey = GetArgData();
  1811.       AddCitation(citeKey);
  1812.       wxNode *node = TexReferences.Find(citeKey);
  1813.       if (node)
  1814.       {
  1815.         TexRef *ref = (TexRef *)node->Data();
  1816.         TexOutput(ref->sectionNumber, TRUE);
  1817.         if (strcmp(ref->sectionNumber, "??") == 0)
  1818.         {
  1819.           char buf[300];
  1820.           sprintf(buf, "Warning: unresolved citation %s.", citeKey);
  1821.           OnInform(buf);
  1822.         }
  1823.       }
  1824.       return FALSE;
  1825.     }
  1826.   }
  1827.   else if (strcmp(macro_name, "nocite") == 0)
  1828.   {
  1829.     if (start && !IsArgOptional())
  1830.     {
  1831.       char *citeKey = GetArgData();
  1832.       AddCitation(citeKey);
  1833.       return FALSE;
  1834.     }
  1835.   }
  1836.   else if (strcmp(macro_name, "helpfontsize") == 0)
  1837.   {
  1838.     if (start)
  1839.     {
  1840.       char *data = GetArgData();
  1841.       if (strcmp(data, "10") == 0)
  1842.         SetFontSizes(10);
  1843.       else if (strcmp(data, "11") == 0)
  1844.         SetFontSizes(11);
  1845.       else if (strcmp(data, "12") == 0)
  1846.         SetFontSizes(12);
  1847.       return FALSE;
  1848.     }
  1849.   }
  1850.   else if (strcmp(macro_name, "pageref") == 0)
  1851.   {
  1852.     if (start)
  1853.     {
  1854.       TexOutput(" ??", TRUE);
  1855.       return FALSE;
  1856.     }
  1857.   }
  1858.   else if (strcmp(macro_name, "parskip") == 0)
  1859.   {
  1860.     if (start && arg_no == 1)
  1861.     {
  1862.       char *data = GetArgData();
  1863.       ParSkip = ParseUnitArgument(data);
  1864.       return FALSE;
  1865.     }
  1866.   }
  1867.   else if (strcmp(macro_name, "parindent") == 0)
  1868.   {
  1869.     if (start && arg_no == 1)
  1870.     {
  1871.       char *data = GetArgData();
  1872.       ParIndent = ParseUnitArgument(data);
  1873.       return FALSE;
  1874.     }
  1875.   }
  1876.   else if (strcmp(macro_name, "sl") == 0)
  1877.   {
  1878.     return OnArgument("it", arg_no, start);
  1879.   }
  1880.   else if (strcmp(macro_name, "typeout") == 0)
  1881.   {
  1882.     if (start)
  1883.       OnInform(GetArgData());
  1884.   }
  1885.   else if (strcmp(macro_name, "footnote") == 0)
  1886.   {
  1887.     if (start)
  1888.       TexOutput(" (", TRUE);
  1889.     else
  1890.       TexOutput(")", TRUE);
  1891.   }
  1892.   else if (strcmp(macro_name, "bibliography") == 0)
  1893.   {
  1894.     if (start)
  1895.     {
  1896.       FILE *fd;
  1897.       char ch;
  1898.       char smallBuf[2];
  1899.       smallBuf[1] = 0;
  1900.       if (fd = fopen(TexBibName, "r"))
  1901.       {
  1902.         ch = getc(fd);
  1903.         smallBuf[0] = ch;
  1904.         while (ch != EOF)
  1905.         {
  1906.           TexOutput(smallBuf);
  1907.           ch = getc(fd);
  1908.           smallBuf[0] = ch;
  1909.         }
  1910.         fclose(fd);
  1911.       }
  1912.       else
  1913.       {
  1914.         OnInform("Run Tex2RTF again to include bibliography.");
  1915.       }
  1916.  
  1917.       // Read in the .bib file, resolve all known references, write out the RTF.
  1918.       char *bibFile = GetArgData();
  1919.       char fileBuf[300];
  1920.       strcpy(fileBuf, bibFile);
  1921.       char *actualFile = TexPathList.FindValidPath(fileBuf);
  1922.       if (!actualFile)
  1923.       {
  1924.         strcat(fileBuf, ".bib");
  1925.         actualFile = TexPathList.FindValidPath(fileBuf);
  1926.       }
  1927.       Bool success = FALSE;
  1928.       if (actualFile)
  1929.       {
  1930.         if (ReadBib(actualFile))
  1931.         {
  1932.           ResolveBibReferences();
  1933.           success = TRUE;
  1934.         }
  1935.       }
  1936.       if (success)
  1937.       {
  1938.         // Write it a new bib section in the appropriate format.
  1939.         FILE *save1 = CurrentOutput1;
  1940.         FILE *save2 = CurrentOutput2;
  1941.         FILE *Biblio = fopen(TexTmpBibName, "w");
  1942.         SetCurrentOutput(Biblio);
  1943.         OutputBib();
  1944.         fclose(Biblio);
  1945.         if (FileExists(TexTmpBibName))
  1946.         {
  1947.           if (FileExists(TexBibName)) wxRemoveFile(TexBibName);
  1948.           wxRenameFile(TexTmpBibName, TexBibName);
  1949.         }
  1950.         SetCurrentOutputs(save1, save2);
  1951.       }
  1952.       else
  1953.         OnError(".bib file not found or malformed.");
  1954.       return FALSE;
  1955.     }
  1956.   }
  1957.   else if (strcmp(macro_name, "multicolumn") == 0)
  1958.   {
  1959.     if (start && (arg_no == 3))
  1960.       return TRUE;
  1961.     else
  1962.       return FALSE;
  1963.   }
  1964.   else if (strcmp(macro_name, "pagestyle") == 0 ||
  1965.            strcmp(macro_name, "cline") == 0 ||
  1966.            strcmp(macro_name, "arabic") == 0 ||
  1967.            strcmp(macro_name, "alph") == 0 ||
  1968.            strcmp(macro_name, "Alph") == 0 ||
  1969.            strcmp(macro_name, "roman") == 0 ||
  1970.            strcmp(macro_name, "Roman") == 0 ||
  1971.            strcmp(macro_name, "setcounter") == 0 ||
  1972.            strcmp(macro_name, "addtocounter") == 0 ||
  1973.            strcmp(macro_name, "addcontentsline") == 0 ||
  1974.            strcmp(macro_name, "newcounter") == 0 ||
  1975.            strcmp(macro_name, "textwidth") == 0 ||
  1976.            strcmp(macro_name, "textheight") == 0 ||
  1977.            strcmp(macro_name, "baselineskip") == 0 ||
  1978.            strcmp(macro_name, "vspace*") == 0 ||
  1979.            strcmp(macro_name, "hspace*") == 0 ||
  1980.            strcmp(macro_name, "vspace") == 0 ||
  1981.            strcmp(macro_name, "hspace") == 0 ||
  1982.            strcmp(macro_name, "vskip*") == 0 ||
  1983.            strcmp(macro_name, "hskip*") == 0 ||
  1984.            strcmp(macro_name, "vskip") == 0 ||
  1985.            strcmp(macro_name, "hskip") == 0 ||
  1986.            strcmp(macro_name, "pagenumbering") == 0)
  1987.     return FALSE;
  1988.   return TRUE;
  1989. }
  1990.  
  1991.